﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace VirtualControl
{
    public class VirtualTimeAxis : VirtualBase
    {
        /// <summary>
        /// 分组类型
        /// </summary>
        public enum TimeAxisType
        {
            Linear,     //线条
            Rectangle   //矩形
        }

        //时间轴成员
        public readonly Dictionary<DateTime, TimeSpan>[] TimeAxisItems;

        //时间轴成员类型
        public readonly TimeAxisType[] TimeAxisTypes;

        //时间轴成员索引
        public int TimeAxisIndex { get; private set; }

        //当前时间轴成员
        public DateTime CurrentItem = DateTime.MinValue;

        public readonly Color[] TimeAxisColors;

        public VirtualTimeAxis(Control parent, TimeAxisType[] types, Color[] colors)
            : base(parent)
        {
            this.TimeAxisTypes = types;
            this.TimeAxisColors = colors;
            this.TimeAxisItems = new Dictionary<DateTime, TimeSpan>[types.Length];
            for (int i = 0; i < types.Length; i++)
                TimeAxisItems[i] = new Dictionary<DateTime, TimeSpan>();
        }

        //当前时间
        public TimeSpan TimeAxisCurrent = new TimeSpan();


        //bool isMouseDown = false;
        int mouseDownX = 0;
        int mouseDownZoomLeft = 0;
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Left)
            {
                if (zoomTimes > 1)
                {
                    isMouseDown = true;

                    mouseDownX = e.X;

                    mouseDownZoomLeft = zoomLeft;
                }
            }
        }

        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            base.OnMouseDoubleClick(e);


        }

        bool isMouseMove = false;
        int mouseMoveX = 0;
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            isMouseMove = true;
            mouseMoveX = e.X;

            long Ticks = (mouseMoveX - zoomLeft) * 24 * 3600 / zoomWidth;
            if (Ticks < 0)
                Ticks = 0;
            else if (Ticks >= 24 * 3600)
                Ticks = 24 * 3600 - 1;

            TimeAxisCurrent = TimeSpan.FromSeconds(Ticks);

            if (isMouseDown)
            {
                zoomLeft = mouseDownZoomLeft + mouseMoveX - mouseDownX;

                if (zoomLeft > 3) zoomLeft = 3;
                else if (zoomLeft < this.Bounds.Right - zoomWidth - 4)
                    zoomLeft = this.Bounds.Right - zoomWidth - 4;
            }

            this.TimeAxisIndex = Math.Max(0, Math.Min(this.TimeAxisItems.Length - 1, e.Y * this.TimeAxisItems.Length / this.Bounds.Height));
            this.CurrentItem = DateTime.MinValue;
            foreach (var time in this.TimeAxisItems[this.TimeAxisIndex])
            {
                if (time.Key.Hour * 3600 + time.Key.Minute * 60 + time.Key.Second + time.Value.TotalSeconds > this.TimeAxisCurrent.TotalSeconds)
                {
                    this.CurrentItem = time.Key;
                    break;
                }
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (isMouseDown)
            {
                isMouseDown = false;
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            isMouseMove = false;
            if (this.CurrentItem != DateTime.MinValue) this.CurrentItem = DateTime.MinValue;
        }

        public void ZoomReset()
        {
            zoomTimes = 1;
            zoomLeft = 3;
            Invalidate();
        }

        int zoomTimes = 1;
        int zoomLeft = 3;
        int zoomWidth
        {
            get { return (this.Bounds.Width - 6) * zoomTimes; }
        }
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);

            int PreZoomTimes = zoomTimes;

            TimeSpan TS = TimeSpan.FromSeconds((e.X - zoomLeft) * 24 * 3600 / zoomWidth);

            if (e.Delta > 0)
            {
                zoomTimes = System.Math.Min(++zoomTimes, 16);
            }
            else if (e.Delta < 0)
            {
                zoomTimes = System.Math.Max(--zoomTimes, 1);
            }

            if (PreZoomTimes != zoomTimes)
            {
                if (zoomTimes == 1)
                    zoomLeft = 3;
                else
                    zoomLeft = 3 + e.X - (int)(TS.TotalSeconds * zoomWidth / (24 * 3600));

                if (zoomLeft > 3) zoomLeft = 3;
                else if (zoomLeft < this.Bounds.Right - zoomWidth - 4)
                    zoomLeft = this.Bounds.Right - zoomWidth - 4;
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            zoomLeft = 3;
        }

        protected override void OnPaint(Graphics G)
        {
            base.OnPaint(G);

            #region 绘制时间轴
            int HourStep = 2;
            if (zoomTimes >= 2) HourStep = 1;
            int MinuteStep = 30;
            if (zoomTimes >= 8) MinuteStep = 15;
            else if (zoomTimes >= 16) MinuteStep = 5;

            lock (this)
            {
                for (int i = 0; i < TimeAxisItems.Length; i++)
                {
                    foreach (var period in TimeAxisItems[i])
                    {
                        TimeSpan ts = new TimeSpan(period.Key.Hour, period.Key.Minute, period.Key.Second);
                        int RecordLeft = zoomLeft + (int)ts.TotalSeconds * zoomWidth / (24 * 3600);
                        Color colorItem = TimeAxisColors[i];
                        if (this.TimeAxisIndex == i && this.CurrentItem == period.Key)
                            colorItem = Color.FromArgb(255 - TimeAxisColors[i].R, 255 - TimeAxisColors[i].G, 255 - TimeAxisColors[i].B);
                        switch (TimeAxisTypes[i])
                        {
                            case TimeAxisType.Linear:       //绘制时间点
                                G.DrawLine(new Pen(colorItem), RecordLeft, this.Bounds.Top + this.Bounds.Height / 2, RecordLeft, this.Bounds.Bottom);
                                break;
                            case TimeAxisType.Rectangle:    //绘制时间段
                                int RecordWidth = (int)period.Value.TotalSeconds * zoomWidth / (24 * 3600) + 1;
                                Rectangle Rect = new Rectangle(RecordLeft, this.Bounds.Top, RecordWidth, this.Bounds.Height / 2);
                                G.FillRectangle(new SolidBrush(colorItem), Rect);
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
            

            //绘制时间标记
            for (int Hour = 0; Hour <= 24; Hour += HourStep)
            {
                int HourLineLeft = zoomLeft + Hour * zoomWidth / 24;

                string HourString = Hour.ToString();
                SizeF HourStringSize = G.MeasureString(HourString, this.Parent.Font);
                float HourStringLeft = HourLineLeft - HourStringSize.Width / 2;
                float HourStringTop = this.Bounds.Top + (int)(this.Bounds.Height - this.Parent.Font.Size) / 2;

                G.DrawLine(Pens.Green, HourLineLeft, this.Bounds.Top, HourLineLeft, HourStringTop);
                G.DrawLine(Pens.Green, HourLineLeft, HourStringTop + this.Parent.Font.Size, HourLineLeft, this.Bounds.Bottom);
                G.DrawString(HourString, this.Parent.Font, Brushes.Green, new PointF(HourStringLeft, HourStringTop));

                if (zoomTimes >= 4)
                {
                    for (int Minute = MinuteStep; Minute < 60; Minute += MinuteStep)
                    {
                        int MinuteLineLeft = HourLineLeft + Minute * zoomWidth / 24 / 60;

                        string MinuteString = Minute.ToString();
                        SizeF MinuteStringSize = G.MeasureString(MinuteString, this.Parent.Font);
                        float MinuteStringLeft = MinuteLineLeft - MinuteStringSize.Width / 2;
                        float MinuteStringTop = this.Bounds.Top + (int)(this.Bounds.Height - this.Parent.Font.Size) / 2;

                        G.DrawLine(Pens.Blue, MinuteLineLeft, this.Bounds.Top, MinuteLineLeft, MinuteStringTop);
                        G.DrawLine(Pens.Blue, MinuteLineLeft, MinuteStringTop + this.Parent.Font.Size, MinuteLineLeft, this.Bounds.Bottom);
                        G.DrawString(MinuteString, this.Parent.Font, Brushes.Blue, new PointF(MinuteStringLeft, MinuteStringTop));
                    }
                }
            }

            //绘制鼠标在时间轴上的时间
            if (isMouseMove)
            {
                string TimeString = TimeAxisCurrent.ToString();

                SizeF TimeStringSize = G.MeasureString(TimeString, this.Parent.Font);

                float TimeStringLeft = mouseMoveX - TimeStringSize.Width / 2;
                float TimeStringTop = this.Bounds.Bottom - TimeStringSize.Height;

                G.DrawString(TimeString, this.Parent.Font, Brushes.Fuchsia, new PointF(TimeStringLeft, TimeStringTop));
            }
            #endregion
        }
    }
}
